package com.zhihesj.anan.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhihesj.anan.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * Spring Security 配置类
 * @EnableGlobalMethodSecurity 开启注解的权限控制，默认是关闭的。
 * prePostEnabled：使用表达式实现方法级别的控制，如：@PreAuthorize("hasRole('ADMIN')")
 * securedEnabled: 开启 @Secured 注解过滤权限，如：@Secured("ROLE_ADMIN")
 * jsr250Enabled: 开启 @RolesAllowed 注解过滤权限，如：@RolesAllowed("ROLE_ADMIN")
 *
 * @author K. L. Mao
 * @create 2019/1/11
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public SecurityConfig(){}

    /**
     * 登陆成功
     */
    @Autowired
    private JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler;

    /**
     * 登陆失败
     */
    @Autowired
    private JwtAuthenticationFailureHandler jwtAuthenticationFailureHandler;

    /**
     * 登出
     */
    @Autowired
    private JwtLogoutSuccessHandler jwtLogoutSuccessHandler;

    /**
     * 身份验证失败
     */
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    /**
     * 权限验证失败
     */
    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;

    /**
     * 用户服务
     */
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    /**
     * token验证
     */
    @Autowired
    private JwtAuthorizationTokenFilter authenticationTokenFilter;

    private ObjectMapper objectMapper;

    /**
     * 从容器中取出 AuthenticationManagerBuilder，执行方法里面的逻辑之后，放回容器
     * @param
     * @throws Exception
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoderBean());
    }


    /**
     * 拦截在这配
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .frameOptions()
                .disable()
                .and()
                .formLogin()
                .loginPage("/login")
                .and()

                .logout()
                .logoutSuccessHandler(jwtLogoutSuccessHandler)
                .permitAll()

                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)
                .and()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                //放开swagger查看权限
                .antMatchers(
                        "/v2/api-docs",
                        "/swagger-resources",
                        "/swagger-resources/**",
                        "/configuration/ui",
                        "/configuration/security",
                        "/swagger-ui.html/**",
                        "/webjars/**",
                        "/gicapi/**"
                ).permitAll()
                //加入模板
                .antMatchers(
                        "/system/user/**",
                        "/system/menu/getMenuList")
                .permitAll()
                .antMatchers(
                        "/magicaldrag/**",
                        "/assets/**",
                        "/lowcode/**"
                ).permitAll()

                // 角色校验时，会自动拼接 "ROLE_"
                .antMatchers("/haha").hasAnyRole("COMMON")
                .antMatchers("/test/**", "/register","/dingtalk/**").permitAll()
                .antMatchers("/druid/**").permitAll()
                .antMatchers("/sysUser/test", "/api/wechat/**", "/weixin/**").permitAll()
                // 剩下所有的链接都需要验证
                .anyRequest().authenticated()
                .and()
                .cors()
                .and()
                // 禁用 Spring Security 自带的跨域处理
                .csrf().disable()
                // 定制我们自己的 session 策略：调整为让 Spring Security 不创建和使用 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                //禁用缓存
        http.headers().cacheControl();
        http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(jwtUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 注册自定义的UsernamePasswordAuthenticationFilter
     */
    @Bean
    JwtUsernamePasswordAuthenticationFilter jwtUsernamePasswordAuthenticationFilter() throws Exception{
        JwtUsernamePasswordAuthenticationFilter filter = new JwtUsernamePasswordAuthenticationFilter();
        filter.setAuthenticationSuccessHandler(jwtAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(jwtAuthenticationFailureHandler);
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

    @Bean
    public PasswordEncoder passwordEncoderBean() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

//    @Bean
//    public JwtFilterInvocationSecurityMetadataSource jwtFilterInvocationSecurityMetadataSource(FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource) {
//        JwtFilterInvocationSecurityMetadataSource securityMetadataSource = new JwtFilterInvocationSecurityMetadataSource(filterInvocationSecurityMetadataSource);
//        ApplicationContext.registerBean(securityMetadataSource);
//        return securityMetadataSource;
//    }

//    @Bean
//    public CorsFilter corsFilter(){
//        UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
//        CorsConfiguration cors = new CorsConfiguration();
//        cors.setAllowCredentials(true);
//        cors.setAllowedOrigins("*");
//        cors.setAllowedHeaders("*");
//        cors.setAllowedMethods("*");
//        configurationSource.registerCorsConfiguration("*/**",cors);
//        return new CorsFilter(configurationSource);
//    }


}
